# Http

<details>
<summary>介绍下 `http1.0`、`http1.1`、`http2.0` 协议的区别？</summary>

`http1.0`
它的特点是每次请求和响应完毕后都会销毁 `TCP` 连接，同时规定前一个响应完成后才能发送下一个请求。这样做有两个问题：

1. 无法复用连接 ，每次请求都要创建新的 `TCP` 连接，完成三次握手和四次挥手，网络利用率低
2. 队头阻塞， 如果前一个请求被某种原因阻塞了，会导致后续请求无法发送。

`http1.1`：

`http1.1` 是 `http1.0` 的改进版，它做出了以下改进：

1. 长连接： `http1.1` 允许在请求时增加请求头`connection:keep-alive`，这样便允许后续的客户端请求在一段时间内复用之前的 `TCP` 连接
2. 管道化：基于长连接的基础，管道化可以不等第一个请求响应继续发送后面的请求，但响应的顺序还是按照请求的顺序返回。
3. 缓存处理：新增响应头 `cache-control`，用于实现客户端缓存。
4. 断点传输：在上传/下载资源时，如果资源过大，将其分割为多个部分，分别上传/下载，如果遇到网络故障，可以从已经上传/下载好的地方继续请求，不用从头开始，提高效率

`http2.0`

`http2.0` 进一步优化了传输效率，它主要有以下改进：

1. 二进制分帧：将传输的消息分为更小的二进制帧，每帧有自己的标识序号，即便被随意打乱也能在另一端正确组装
2. 多路复用：基于二进制分帧，在同一域名下所有访问都是从同一个 `TCP` 连接中走，并且不再有队头阻塞问题，也无须遵守响应顺序
3. 头部压缩：`http2.0` 通过字典的形式，将头部中的常见信息替换为更少的字符，极大的减少了头部的数据量，从而实现更小的传输量
4. 服务器推：`http2.0` 允许服务器直接推送消息给客户端，无须客户端明确的请求

</details>

<details>
<summary>为什么 `HTTP1.1` 不能实现多路复用？</summary>

`HTTP1.1` 不是二进制传输，而是通过文本进行传输。由于没有流的概念，在使用并行传输（多路复用）传递数据时，接收端在接收到响应后，并不能区分多个响应分别对应的请求，所以无法将多个响应的结果重新进行组装，也就实现不了多路复用。

</details>

<details>
  <summary>简单讲解一下 `http2` 的多路复用</summary>

在 HTTP/2 中，有两个非常重要的概念，分别是帧（frame）和流（stream）。 帧代表着最小的数据单位，每个帧会标识出该帧属于哪个流，流也就是多个帧组成的数据流。 多路复用，就是在一个 TCP 连接中可以存在多条流。换句话说，也就是可以发送多个请求，对端可以通过帧中的标识知道属于哪个请求。通过这个技术，可以避免 HTTP 旧版本中的队头阻塞问题，极大的提高传输性能。

</details>

<details>
<summary>谈谈你对 TCP 三次握手和四次挥手的理解</summary>

TCP 协议通过三次握手建立可靠的点对点连接，具体过程是：

首先服务器进入监听状态，然后即可处理连接

第一次握手：建立连接时，客户端发送 syn 包到服务器，并进入 SYN_SENT 状态，等待服务器确认。在发送的包中还会包含一个初始序列号 seq。此次握手的含义是客户端希望与服务器建立连接。

第二次握手：服务器收到 syn 包，然后回应给客户端一个 SYN+ACK 包，此时服务器进入 SYN_RCVD 状态。此次握手的含义是服务端回应客户端，表示已收到并同意客户端的连接请求。

第三次握手：客户端收到服务器的 SYN 包后，向服务器再次发送 ACK 包，并进入 ESTAB_LISHED 状态。

最后，服务端收到客户端的 ACK 包，于是也进入 ESTAB_LISHED 状态，至此，连接建立完成

当需要关闭连接时，需要进行四次挥手才能关闭

1. Client 向 Server 发送 FIN 包，表示 Client 主动要关闭连接，然后进入 FIN_WAIT_1 状态，等待 Server 返回 ACK 包。此后 Client 不能再向 Server 发送数据，但能读取数据。
2. Server 收到 FIN 包后向 Client 发送 ACK 包，然后进入 CLOSE_WAIT 状态，此后 Server 不能再读取数据，但可以继续向 Client 发送数据。
3. Client 收到 Server 返回的 ACK 包后进入 FIN_WAIT_2 状态，等待 Server 发送 FIN 包。
4. Server 完成数据的发送后，将 FIN 包发送给 Client，然后进入 LAST_ACK 状态，等待 Client 返回 ACK 包，此后 Server 既不能读取数据，也不能发送数据。
5. Client 收到 FIN 包后向 Server 发送 ACK 包，然后进入 TIME_WAIT 状态，接着等待足够长的时间（2MSL）以确保 Server 接收到 ACK 包，最后回到 CLOSED 状态，释放网络资源。
6. Server 收到 Client 返回的 ACK 包后便回到 CLOSED 状态，释放网络资源。

  </details>

<details>
<summary>介绍 HTTPS 握手过程？</summary>

7. 客户端请求服务器，并告诉服务器自身支持的加密算法以及密钥长度等信息
8. 服务器响应公钥和服务器证书
9. 客户端验证证书是否合法，然后生成一个会话密钥，并用服务器的公钥加密密钥，把加密的结果通过请求发送给服务器
10. 服务器使用私钥解密被加密的会话密钥并保存起来，然后使用会话密钥加密消息响应给客户端，表示自己已经准备就绪
11. 客户端使用会话密钥解密消息，知道了服务器已经准备就绪。
12. 后续客户端和服务器使用会话密钥加密信息传递消息

  </details>
